/*
 * Copyright (c) 2008, Xiong Yingfei, the University of Tokyo All rights
 * reserved.
 */
package EJBTool.common;

import java.util.Iterator;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.gmf.runtime.common.core.command.CompositeCommand;
import org.eclipse.gmf.runtime.common.core.command.IdentityCommand;
import org.eclipse.gmf.runtime.common.core.command.ICommand;
import org.eclipse.gmf.runtime.common.core.util.Log;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.diagram.ui.commands.CommandProxy;
import org.eclipse.gmf.runtime.diagram.ui.commands.CreateCommand;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIDebugOptions;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIPlugin;
import org.eclipse.gmf.runtime.diagram.ui.internal.DiagramUIStatusCodes;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramCommandStack;
import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditDomain;
import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
import org.eclipse.gmf.runtime.emf.type.core.commands.CreateElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.commands.DestroyElementCommand;
import org.eclipse.gmf.runtime.emf.type.core.requests.DestroyElementRequest;

public class SynchronizingCommandStack extends DiagramCommandStack
{

	public SynchronizingCommandStack(IDiagramEditDomain editDomain)
	{
		super(editDomain);
	}

	@Override
	protected void execute(ICommand command1, IProgressMonitor progressMonitor)
	{
		if (progressMonitor == null)
			progressMonitor = new NullProgressMonitor();
		try
		{
			System.out.println("command executed!" + command1.getClass());
			command1.addContext(getUndoContext());
			beforeExecution();
			getOperationHistory().execute(command1, progressMonitor, null);
			afterExecution();
			IUndoableOperation undoOperation1 = getOperationHistory().getUndoOperation(getUndoContext());
			ICommand command2 = getExtraCommand();
			getOperationHistory().execute(command2, progressMonitor, null);
			IUndoableOperation undoOperation2 = getOperationHistory().getUndoOperation(getUndoContext());
			
			findCreation("",  command1);
			
//			getOperationHistory().replaceOperation(undoOperation2, new IUndoableOperation[] {});
//			getOperationHistory().replaceOperation(undoOperation1, new IUndoableOperation[] {undoOperation2, undoOperation1});
		}
		catch (ExecutionException e)
		{
			System.out.println("exception!!" + e);
			Trace.catching(DiagramUIPlugin.getInstance(),
					DiagramUIDebugOptions.EXCEPTIONS_CATCHING, getClass(),
					"execute", e); //$NON-NLS-1$
			Log.error(DiagramUIPlugin.getInstance(),
					DiagramUIStatusCodes.COMMAND_FAILURE, "execute", e); //$NON-NLS-1$
		}
	}

	private void findCreation(String prefix, Object command1)
	{
		System.out.println(prefix + command1.getClass());
		if (command1 instanceof ICommand) {
			command1 = ((ICommand)command1).reduce();
		}
		if (command1 instanceof CreateElementCommand) {
			System.out.println("something created!");
			_lastcreated = ((CreateElementCommand)command1).getNewElement();
		}else if (command1 instanceof CompositeCommand) {
			CompositeCommand c = (CompositeCommand)command1;
			Iterator i = c.iterator();
			while(i.hasNext()) {
				ICommand next = (ICommand) i.next();
				findCreation(prefix + "\t", next);
			}
		}else if (command1 instanceof CommandProxy) {
			findCreation(prefix + "\t", ((CommandProxy)command1).getCommand());
		}else if (command1 instanceof CompositeTransactionalCommand) {
			CompositeTransactionalCommand c = (CompositeTransactionalCommand) command1;
			Iterator i = c.iterator();
			while(i.hasNext()) {
				ICommand next = (ICommand) i.next();
				findCreation(prefix + "\t", next);
			}
		}
	}
	
	private static EObject _lastcreated;

	private ICommand getExtraCommand()
	{
		if (_lastcreated != null) {
			DestroyElementCommand result = new DestroyElementCommand(new DestroyElementRequest(_lastcreated, false));
			_lastcreated = null;
			System.out.println("destroy command executed!");
			return result;
		}
		// TODO Auto-generated method stub
		return IdentityCommand.INSTANCE;
	}

	private void afterExecution()
	{
		// TODO Auto-generated method stub
		
	}

	private void beforeExecution()
	{
		// TODO Auto-generated method stub
		
	}

}
